

function Swiper(selector) {
    // 轮播的容器
    this.wrap = document.querySelector(selector);
    this.index = 0;
    this.timer = null;

    this.init();
}

Swiper.prototype.init = function () {
    if (this.wrap) {
        this.getEle();  //先获取元素
        this.autoComplete();  // 动态生成导航 追加图片 计算容器宽度
        this.bindEvent(); // 绑定事件 
        this.autoPlay(); // 自动轮播
    }
}
Swiper.prototype.getEle = function () {
    // this ->  swiperObj
    this.nav = this.wrap.getElementsByClassName("nav")[0];
    this.swiper = this.wrap.getElementsByClassName("swiper")[0];
    this.liList = this.nav.getElementsByTagName("li");
    this.swiperItems = this.swiper.getElementsByClassName("swiper-item");
    this.prev = this.wrap.getElementsByClassName("prev")[0];
    this.next = this.wrap.getElementsByClassName("next")[0];
    this.swiperWidth = this.wrap.clientWidth;
};
Swiper.prototype.autoComplete = function () {
    // 动态生成

    // 1. 生成对应图片个数的li放到nav中  
    for (var i = 0; i < this.swiperItems.length; i++) {
        var li = document.createElement("li");
        if (i == this.index) { // i==0
            li.classList.add("active");
        }
        this.nav.appendChild(li);
    }

    // 2. swiper中的第一个li 克隆 放到最后面
    var cloneFirst = this.swiper.firstElementChild.cloneNode(true);
    this.swiper.appendChild(cloneFirst);

    // swiper的宽度 =  (n+1) * wrap的宽度   => 四张图片  (4+1)*100%
    // this.swiperItems 传统方法获取元素 -> 自动更新
    this.swiper.style.width = this.swiperItems.length * this.swiperWidth + "px";

    // 单个swiper-item的宽度 = 100 / (n+1) + "%" =>   100 / (4+1) => 20%
    for (var i = 0; i < this.swiperItems.length; i++) {
        var swiperItem = this.swiperItems[i];
        swiperItem.style.width = (100 / this.swiperItems.length) + "%";
    }
};
Swiper.prototype.bindEvent = function () {
    // this -> swiperObj
    this.click();
    this.hover();
    this.switch();
};
Swiper.prototype.click = function () {   // swiperObj.click
    // debugger;
    // this -> swiperObj
    var _this = this;
    for (let i = 0; i < this.liList.length; i++) {  // i=> 0-5
        let li = this.liList[i];  //获取对应下标的元素
        li.onclick = function () { // this-> 被点击的li
            // 点击时记录下标  => 下次从点击位置开始轮播
            _this.index = i;

            _this.step();

        }
    }
};
Swiper.prototype.hover = function () {// swiperObj
    // this -> swiperObj
    this.wrap.onmouseenter = () => {
        clearInterval(this.timer);
    }

    this.wrap.onmouseleave = () => {
        this.autoPlay();
    }

};
Swiper.prototype.switch = function () {

    this.prev.onclick = () => {

        this.index--;  // 0 1 2 3  

        this.step();

    }
    this.next.onclick = () => {
        this.index++;  // 0 1 2 3  
        // console.log(index);
        this.step();

    }
};
Swiper.prototype.autoPlay = function (delay = 3000) {  // swiperObj.autoPlay()
    // this -> swiperObj
    clearInterval(this.timer);
    this.timer = setInterval(() => {
        this.index++;
        this.step();
    }, delay)
};
Swiper.prototype.step = function () {

    if (this.index < 0) {  // 超出左边的临界值
        this.index = this.swiperItems.length - 1; // 5-1 => 4  (第五张下标)
        this.swiper.style.left = -(this.swiperWidth * this.index) + "px";  //切换到第五张

        this.index--;
    }

    if (this.index > this.swiperItems.length - 1) { // 如果超出第五张 (index > 4) 
        // 瞬间切换到第一张 
        this.swiper.style.left = 0;
        this.index = 0;  //第一张下标   

        this.index++;  // 下标切到第二张 => 后续会执行animate()  滚动到第二张

    }

    for (var j = 0; j < this.liList.length; j++) {
        this.liList[j].className = ""; // 清除每一个导航的class名
    }
    var activeIndex = this.index == this.swiperItems.length - 1 ? 0 : this.index;
    this.liList[activeIndex].className = "active";

    this.animate(this.swiper, { left: -(this.swiperWidth * this.index) }, "slow", () => {
        // 每次滚动结束时 会执行的回调函数
        // console.log("index", index);

        // 每次滚动结束时 判断是否滚动到第五张(下标: 4) 
        if (this.index >= this.swiperItems.length - 1) { // index >= 4 (滚动第五张)
            this.swiper.style.left = 0;
            this.index = 0;
        }

    })
};
Swiper.prototype.animate = function (ele, params, type = "normal", callback) {
    // debugger;
    // callback 形参 -> 接收实际参数(本次有点特殊 -> 接收的是一个函数) 


    /* 获取非行内样式 */
    function getStyle(ele, cssKey) {
        if (window.getComputedStyle) {
            return window.getComputedStyle(ele)[cssKey];
        } else {
            return ele.currentStyle[cssKey];
        }
    }


    // 记录单属性运动的 cur end speed
    // var cur = ele.offsetLeft;  // 1. 记录小球的起始位置(left)  2. 每次运动后小球的位置
    // var cur = parseFloat(getStyle(ele, cssKey));  // 1. 记录小球的起始位置(left)  2. 每次运动后小球的位置
    // end = parseFloat(end); //去单位 ("1000px" => 1000)
    // var speed = 0;

    var cur = {};   // {left:当前值,top:当前值}
    var end = {};   // {left:终点,top:终点}  单位处理
    var speed = {}  // {left:速度,top:速度}  记录速度

    for (var cssKey in params) {  // csskey => 运动的css属性
        cur[cssKey] = parseFloat(getStyle(ele, cssKey));
        end[cssKey] = parseFloat(params[cssKey]);
        speed[cssKey] = 0;
    }
    // console.log("起始位置", cur);
    // console.log("终点", end);
    // console.log("速度", speed);

    // ele => 运动的元素(元素节点 -> 对象)  -> 元素节点的内置属性(className,id) 和 对象自定义属性
    // var data = {};
    // data.a = 1;
    // data.b = 2;

    // 将计时器的编号 作为元素的属性 存储到元素上(每个运动的元素都有一个timer属性 => 计时器的编号)
    // ele.timer = 1;

    clearInterval(ele.timer);
    ele.timer = setInterval(function () {

        // 多属性同时运动
        var isFinished = true;  // 假设都到达终点

        // {left:"1000px",top:500}
        for (var cssKey in params) {  // csskey => 运动的css属性  "left"  "top"

            if (type == "normal") {
                // 匀速运动
                if (end[cssKey] > cur[cssKey]) {
                    speed[cssKey] = 20
                } else if (end[cssKey] < cur[cssKey]) {
                    speed[cssKey] = -20;
                } else {
                    speed[cssKey] = 0;
                }

            } else if (type == "fast") {
                // 加速运动
                if (end[cssKey] > cur[cssKey]) {  // 正向运动(0-1000   => speed正值)  
                    speed[cssKey] += 2;
                } else if (end[cssKey] < cur[cssKey]) { // 反向运动(1000 - 0   => speed负值) 
                    speed[cssKey] -= 2;
                } else {
                    speed[cssKey] = 0;
                }

            } else if (type == "slow") {
                // 缓冲运动
                // (终点值 - 当前位置)  => 剩余的距离
                // 剩余的距离 / 缓冲因子(n) => (每次剩余的n分之1)

                // 缓冲因子 => 一般在8-12之间

                if (end[cssKey] > cur[cssKey]) {
                    speed[cssKey] = (end[cssKey] - cur[cssKey]) / 10;  // speed >0 =>  可能会出现 0.00001
                    speed[cssKey] = Math.ceil(speed[cssKey]);  //  如果速度小于1  取  1
                } else if (end[cssKey] < cur[cssKey]) {
                    speed[cssKey] = (end[cssKey] - cur[cssKey]) / 10;  // speed < 0 =>  可能会出现-0.00001
                    speed[cssKey] = Math.floor(speed[cssKey]);  //  如果速度大于-1  取  -1
                } else {
                    speed[cssKey] = 0;
                }

            }

            // console.log(speed);
            cur[cssKey] += speed[cssKey];  // 每次运动后小球的位置
            ele.style[cssKey] = cur[cssKey] + "px";

            if (Math.abs(cur[cssKey] - end[cssKey]) <= Math.abs(speed[cssKey])) {  // 到达终点后停下
                ele.style[cssKey] = end[cssKey] + "px";  // 直接到达终点
                delete params[cssKey];   //如果当前属性到达终点 => 移出该属性 (不会再遍历该属性)
                // clearInterval(timer);   // 有一个到达终点就停下  
            } else {  // 有一个没到达终点   => 推翻假设
                isFinished = false;
            }


        }
        // console.log(isFinished);
        if (isFinished) {   ///全都到达终点(本次运动结束)=> 清除计时器
            clearInterval(ele.timer);
            if (callback && typeof callback == "function") {  //如果callback有值 且 是函数
                callback(); //执行该函数  -> 每次运动结束之后执行函数
            }
        }

    }, 10);
};

